#include "mondialogueposterisation.h"
#include "ui_mondialogueposterisation.h"
#include <iostream>
#include <time.h>
#include "mainwindow.h"
#include "fenetreimage.h"

using namespace std;

MonDialoguePosterisation::MonDialoguePosterisation(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MonDialoguePosterisation)
{
    ui->setupUi(this);

    fenetreImage = (FenetreImage*) parent;
    hauteur = fenetreImage->getCalqueCourant()->height();
    largeur = fenetreImage->getCalqueCourant()->width();

    Calque *copie = fenetreImage->getCalqueCourant()->copie();

    ElementHistorique* eh = new ElementHistorique(QString("posterisation"), copie);
    fenetreImage->historique.ajouter(eh);

    tabImage = new QRgb*[hauteur];
    for(int i = 0; i < hauteur; i++) {
        tabImage[i] = new QRgb[largeur];
    }


    for(int x=0; x< largeur; x++){
        for(int y=0; y< hauteur; y++){
            tabImage[y][x] = fenetreImage->getCalqueCourant()->pixel(x,y);
        }
    }
    on_spinBox_valueChanged(2);
}

MonDialoguePosterisation::~MonDialoguePosterisation()
{
    delete ui;
    for(int i = 0; i < hauteur; i++) {
       delete[] tabImage[i];
    }
    delete [] tabImage;
}

void MonDialoguePosterisation::on_horizontalSlider_valueChanged(int value)
{
    ui->spinBox->setValue(value);
}


void MonDialoguePosterisation::on_spinBox_valueChanged(int value)
{
    nbCouleurs = value;

    //int nbCouleurs = monDialogue->getNbCouleurs();

    int largeur = fenetreImage->largeur;
    int hauteur = fenetreImage->hauteur;

    QRgb* couleurNoyau = new QRgb[nbCouleurs];
    decompte* noyautmp = new decompte[nbCouleurs];

    srand(time(NULL));

    for(int i=0; i<nbCouleurs; i++){
        couleurNoyau[i]=tabImage[rand()%hauteur][rand()%largeur];
    }

    int nbcycle=0;
    bool changed;
    do {
        changed = false;

        //raz du noyau tmp
        for(int i=0; i<nbCouleurs; i++){
            noyautmp[i].rouge = 0;
            noyautmp[i].vert = 0;
            noyautmp[i].bleu = 0;
            noyautmp[i].nb = 0;
        }

        //On reparti les points dans les classes
        for(int x=0; x<largeur; x+=3) {
            for(int y=0; y<hauteur; y+=2) {
                QRgb couleurCourante = tabImage[y][x];
                int indexNoyau=0;

                //cherche le noyau le plus proche
                for(int k=1; k<nbCouleurs; k++) {
                    if(distance (couleurCourante, couleurNoyau[k]) <
                            distance (couleurCourante,couleurNoyau[indexNoyau])) {
                        indexNoyau=k;
                    }
                }
                noyautmp[indexNoyau].rouge += qRed(couleurCourante);
                noyautmp[indexNoyau].vert += qGreen(couleurCourante);
                noyautmp[indexNoyau].bleu += qBlue(couleurCourante);
                noyautmp[indexNoyau].nb++;
            }
        }

        //on recalcule les noyaux
        for(int i=0; i<nbCouleurs; i++){
            int nbPix = noyautmp[i].nb;
            QRgb nouveauNoyau = qRgb(noyautmp[i].rouge/nbPix, noyautmp[i].vert/nbPix, noyautmp[i].bleu/nbPix);
            if(distance(nouveauNoyau,couleurNoyau[i]) > 5) {
                couleurNoyau[i] = nouveauNoyau;
                changed=true;
            }
        }
    nbcycle++;
    } while (changed);


    Calque* calque = fenetreImage->getCalqueCourant();

    for(int y=0; y<hauteur; y++) {
        uint* line = (uint*) calque->scanLine(y);
    for(int x=0; x<largeur; x++) {
            QRgb couleurCourante = tabImage[y][x];
            int indexNoyau=0;
            for(int k=1; k<nbCouleurs; k++) {
                if(distance (couleurCourante, couleurNoyau[k]) <
                        distance (couleurCourante,couleurNoyau[indexNoyau])) {
                    indexNoyau=k;
                }
            }
            line[x] = qRgb(qRed(couleurNoyau[indexNoyau]), qGreen(couleurNoyau[indexNoyau]), qBlue(couleurNoyau[indexNoyau]));
            //calque->setPixel(x,y, couleurNoyau[indexNoyau]);
        }
    }

    fenetreImage->a_ete_modifie=true;
    fenetreImage->updateCalqueCourant();

    delete[] couleurNoyau;
    delete[] noyautmp;
}

int MonDialoguePosterisation::getNbCouleurs(){
   return nbCouleurs;
}

double MonDialoguePosterisation::distance(QRgb c1, QRgb c2) {
    return (sqrt( pow(qRed(c1)-qRed(c2),2) +
            pow(qGreen(c1)-qGreen(c2),2)+pow(qBlue(c1)-qBlue(c2),2)));
}
